﻿using System;
using System.Collections.Generic;
using System.Linq;

using System.Data;
using Prodma.DataAccess.Database;
using Prodma.DataAccess.Interfaces.Models;
using Prodma.DataAccess.Models.ViewModels;
using Prodma.DataAccess.Repositories;
using Prodma.DataAccess.Helper.Enumerators;

namespace Prodma.DataAccess.DataService
{
    public class MenuService : IMenuRepository
    {

        private DataContext context = new DataContext();


        #region IMenuRepository Members

        public IList<MenuVm> GetList(int location)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var list = (from menu in context.tb_Menu
                            join order in context.tb_MenuOrder
                                on menu.Id equals order.Menu
                            where menu.tb_MenuLocation.Id == location
                            select new MenuVm()
                            {
                                Id = menu.Id,
                                Parent = new ParentMenuVm() { Id = menu.ParentId },
                                Location = new MenuLocationVm() { Id = menu.tb_MenuLocation.Id, Name = menu.tb_MenuLocation.Name },
                                Type = new MenuTypeVm() { Id = menu.tb_MenuType.Id, Name = menu.tb_MenuType.Name },
                                Name = menu.Name,
                                Item = menu.Item,
                                Url = menu.Url,
                                Order = new MenuOrderVm() { Id = order.Id, OrderNo = order.OrderNo },
                                State = new StateVm() { Id = menu.tb_State.Id, Name = menu.tb_State.Name },
                                SubItemCount = 0
                            }).OrderBy(x => x.Order.OrderNo).ToList();

                return list;
            }
        }
        #endregion

        #region IRecordOperation<tb_Menu,MenuVm> Members

        public IList<MenuVm> GetList()
        {
            throw new NotImplementedException();
        }

        public void New(tb_Menu entity)
        {
            DataContext context = new DataContext();
            using (context)
            {
                context.AddTotb_Menu(entity);
                context.SaveChanges();
            }
        }
        public MenuVm Edit(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var edit = (from menu in context.tb_Menu
                            where menu.Id == id
                            select new MenuVm()
                            {
                                Id = menu.Id,
                                Parent = new ParentMenuVm() { Id = menu.ParentId },
                                Location = new MenuLocationVm() { Id = menu.tb_MenuLocation.Id, Name = menu.tb_MenuLocation.Name },
                                Type = new MenuTypeVm() { Id = menu.tb_MenuType.Id, Name = menu.tb_MenuType.Name },
                                Name = menu.Name,
                                Item = menu.Item,
                                Url = menu.Url,
                                Target = menu.Target,
                                State = new StateVm() { Id = menu.tb_State.Id, Name = menu.tb_State.Name }
                            }).FirstOrDefault();
                return edit;
            }
        }
        public void Update(int id, tb_Menu entity)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var edit = (from menu in context.tb_Menu
                            where menu.Id == id
                            select menu).FirstOrDefault();

                edit.tb_MenuTypeReference.EntityKey = entity.tb_MenuTypeReference.EntityKey;
                edit.Name = entity.Name;
                edit.Item = entity.Item;
                edit.Url = entity.Url;
                edit.Target = entity.Target;
                edit.tb_StateReference.EntityKey = entity.tb_StateReference.EntityKey;

                context.SaveChanges();
            }
        }
        public void Delete(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var delete = (from menu in context.tb_Menu
                              where menu.Id == id
                              select menu).FirstOrDefault();

                if (delete == null)
                {
                    return;
                }

                context.DeleteObject(delete);
                context.SaveChanges();
            }
        }
        #endregion

        #region IOrderOperation<MenuOrderVm> Members

        public void OrderUp(int id, MenuOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var currentOrder = (from order in context.tb_MenuOrder
                                    where order.Menu == viewModel.MenuId &&
                                          order.tb_MenuLocation.Id == viewModel.Location &&
                                          order.ParentId == viewModel.ParentId &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();



                var previousMenuOrder = (from order in context.tb_MenuOrder
                                         where order.OrderNo < viewModel.OrderNo &&
                                               order.tb_MenuLocation.Id == viewModel.Location &&
                                               order.ParentId == viewModel.ParentId
                                         select order).OrderByDescending(x => x.OrderNo).FirstOrDefault();

                if (previousMenuOrder != null)
                {
                    previousMenuOrder.OrderNo++;
                    currentOrder.OrderNo--;
                }

                context.SaveChanges();
            }
        }
        public void OrderDown(int id, MenuOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var currentOrder = (from order in context.tb_MenuOrder
                                    where order.Menu == viewModel.MenuId &&
                                          order.tb_MenuLocation.Id == viewModel.Location &&
                                          order.ParentId == viewModel.ParentId &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();

                var nextOrder = (from order in context.tb_MenuOrder
                                 where order.OrderNo > viewModel.OrderNo &&
                                       order.tb_MenuLocation.Id == viewModel.Location &&
                                       order.ParentId == viewModel.ParentId
                                 select order).OrderBy(x => x.OrderNo).FirstOrDefault();

                if (nextOrder != null)
                {
                    nextOrder.OrderNo--;
                    currentOrder.OrderNo++;
                }

                context.SaveChanges();
            }
        }
        public void SetOrder(int id, MenuOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var lastOrder = (from order in context.tb_MenuOrder
                                 where order.tb_MenuLocation.Id == viewModel.Location &&
                                       order.ParentId == viewModel.ParentId
                                 select order).OrderByDescending(x => x.OrderNo).FirstOrDefault();

                if (viewModel.SetOrderNo >= lastOrder.OrderNo)
                {
                    return;
                }

                var currentOrder = (from order in context.tb_MenuOrder
                                    where order.Menu == viewModel.MenuId &&
                                          order.tb_MenuLocation.Id == viewModel.Location &&
                                          order.ParentId == viewModel.ParentId &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();

                currentOrder.OrderNo = viewModel.SetOrderNo;
                int fark = viewModel.SetOrderNo - viewModel.OrderNo;

                if (fark > 0)
                {
                    var nextOrder = (from order in context.tb_MenuOrder
                                     where order.OrderNo > viewModel.OrderNo &&
                                           order.OrderNo <= viewModel.SetOrderNo &&
                                           order.tb_MenuLocation.Id == viewModel.Location &&
                                           order.ParentId == viewModel.ParentId
                                     select order).OrderBy(x => x.OrderNo).ToList();

                    foreach (tb_MenuOrder m in nextOrder)
                    {
                        m.OrderNo--;
                        context.SaveChanges();
                    }
                }
                else if (fark <= 0)
                {
                    var previousOrder = (from order in context.tb_MenuOrder
                                         where order.OrderNo < viewModel.OrderNo &&
                                               order.OrderNo >= viewModel.SetOrderNo &&
                                               order.tb_MenuLocation.Id == viewModel.Location &&
                                               order.ParentId == viewModel.ParentId
                                         select order).OrderBy(x => x.OrderNo).ToList();

                    foreach (tb_MenuOrder m in previousOrder)
                    {
                        m.OrderNo++;
                        context.SaveChanges();
                    }
                }
            }
        }
        #endregion

        #region IStateOperation Members

        public void SetActive(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var viewState = (from menu in context.tb_Menu
                                 where menu.Id == id
                                 select menu).FirstOrDefault();

                viewState.tb_StateReference.EntityKey = new EntityKey("DataContext.tb_State", "Id", Convert.ToInt32(State.Active));

                context.SaveChanges();
            }
        }
        public void SetPassive(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var viewState = (from menu in context.tb_Menu
                                 where menu.Id == id
                                 select menu).FirstOrDefault();

                viewState.tb_StateReference.EntityKey = new EntityKey("DataContext.tb_State", "Id", Convert.ToInt32(State.Passive));

                context.SaveChanges();
            }
        }
        #endregion

    }
}
